unit oStats;

interface

uses
  uOSPABA, Generics.Collections;

type
  TSimpleStat = class
    strict private
      aVal: TList<Double>;
    public
      constructor create;
      destructor Destroy; override;
      procedure AddVal(paValue: Double);
      procedure Reset;
      function Mean: Double;
      function Dispersion: Double;
      property Values : TList<Double> read aVal;
  end;

  TWaitStat = class
    strict private
      aFrom: Double;
      aTo: Double;
    public
      constructor create;
      procedure StartWaiting(paFrom: Double);
      procedure EndWaiting(paTo: Double);
      function WaitTime: Double;
  end;

  TAddStat = class
    strict private
      aVal: Double;
    public
      property Value: Double read aVal;
      constructor create;
      procedure AddVal(paValue: Double);
      procedure Reset;
  end;

  TXYStat = class
    strict private
      aX: TList<Double>;
      aY: TList<Double>;
    public
      constructor create;
      destructor Destroy; override;
      procedure AddXY(paX, paY: Double);
      procedure Reset(paX, paY: Double);
      function Mean: Double;
      function Dispersion: Double;
      function LastVal: Double;
  end;

implementation

{ TStat }

procedure TSimpleStat.AddVal(paValue: Double);
begin
  aVal.Add(paValue);
end;

constructor TSimpleStat.create;
begin
  aVal := TList<Double>.create;
end;

destructor TSimpleStat.Destroy;
begin
  aVal.Free;
  inherited;
end;

function TSimpleStat.Dispersion: Double;
var
  v: Double;
  d: Double;
begin
  d := 0;
  for v in aVal do d := d + sqr(Mean - v);
  if aVal.Count > 1 then
    result := sqrt(d / (aVal.Count - 1))
  else
    Result := 0;
end;

function TSimpleStat.Mean: Double;
var
  m: Double;
  v: Double;
begin
  m := 0;
  if aVal.Count = 0
    then result := m
    else begin
      for v in aVal do m := m + v;
      result := m / aVal.Count;
    end;
end;

procedure TSimpleStat.Reset;
begin
  aVal.Clear;
end;

{ TAddStat }

procedure TAddStat.AddVal(paValue: Double);
begin
  aVal := aVal + paValue;
end;

constructor TAddStat.create;
begin
  Reset;
end;

procedure TAddStat.Reset;
begin
  aVal := 0;
end;

{ TXYStat }

procedure TXYStat.AddXY(paX, paY: Double);
begin
  if aY[aY.Count - 1] = paY then begin
    aX[ax.Count - 1] := ax[ax.Count - 1] + 1;
    exit;
  end;
  aX.Add(paX);
  aY.Add(paY);
end;

constructor TXYStat.create;
begin
  aX := TList<Double>.create;
  aY := TList<Double>.create;
end;

destructor TXYStat.Destroy;
begin
  aX.Free;
  aY.Free;
  inherited;
end;

function TXYStat.Dispersion: Double;
var
  v: Double;
  d: Double;
begin
  d := 0;
  for v in aX do d := d + sqr(Mean - v);
  if aX.Count > 1 then
    result := d / (ax.Count - 1 )
  else
    Result := 0;
end;

function TXYStat.LastVal: Double;
begin
  if aX.Count = 0
    then result := 0
    else result := aX.Items[aX.Count - 1];
end;

function TXYStat.Mean: Double;
var
  i: Integer;
  sumX: Double;
  sumY: Double;
  vaha: Double;
begin
  sumX := 0;
  sumY := 0;
  for i := 2 to aY.Count - 1 do
    begin
      vaha := aY.Items[i] - aY.Items[i - 1];
      sumY := sumY + vaha;
      sumX := sumX + vaha * aX.Items[i - 1];
    end;
  if sumY = 0
    then result := 0
    else result := sumX / sumY;
end;


procedure TXYStat.Reset(paX, paY: Double);
begin
  aX.Clear;
  aY.Clear;
  aX.Add(paX);
  aY.Add(paY);
end;

{ TWaitStat }

constructor TWaitStat.create;
begin
  aFrom := 0;
  aTo := 0;
end;

procedure TWaitStat.EndWaiting(paTo: Double);
begin
  if paTo < aFrom
    then aTo := aFrom
    else aTo := paTo;
end;

procedure TWaitStat.StartWaiting(paFrom: Double);
begin
  aFrom := paFrom;
end;

function TWaitStat.WaitTime: Double;
begin
  result := aTo - aFrom;
end;

end.


